#!/usr/bin/perl
#
# Copyright (c) Huawei Software Technologies Co., Ltd.
#
# History:
#   2012-05-26 Output files count to xml report.
#   2011-05-27 Fix bug: Wrong value for duplicate files.
#   2011-01-31 Output xml format.
#   2010-03-24 Update to lcov v1.8, support branch coverage.
#   2009-09-30 Created by ZhuJunling <zhujunling@huawei.com>
#

use strict;
use integer;

sub LINE() { 0 }
sub FUNC() { 1 }
sub BRANCH() { 2 }

if (@ARGV != 2) {
    $0 =~ s{.*[\\/]}{};
    die "Usage: $0 <infofile> <xmlfile>\n";
}

my $cover_line = 0;
my $total_line = 0;
my $cover_func = 0;
my $total_func = 0;
my $cover_branch = 0;
my $total_branch = 0;
my %cover_file_by;

read_info($ARGV[0]);
write_xml($ARGV[1]);
#### end of main ####


sub suffixname {
    shift =~ m{\.([^.:/\\]+)$};
    return $1;
}

sub read_info {
    my $infofile = shift;
    open INFO, '<', $infofile or die "Open file error: $!\n";

    my (%data, $file);
    while (<INFO>) {
        s/\015?\012$//;
        if (m/^[SK]F:(.*)/) {
            #SF:<absolute path to the source file>
            $file = $1;
        }
        elsif (m/^DA:(\d+),(-?\d+)/) {
            #DA:<line number>,<execution count>[,<checksum>]
            my $count = $2 < 0 ? 0 : $2;
            $data{$file}[LINE]{$1} += $count;
        }
        elsif (m/^FNDA:(\d+),([^,]+)/) {
            #FNDA:<execution count>,<function name>
            $data{$file}[FUNC]{$2} += $1;
        }
        elsif (m/^BRDA:(\d+),(\d+),(\d+),(\d+|-)/) {
            #BRDA:<line number>,<block number>,<branch number>,<taken>
            my $branch = join(',', $1, $2, $3);
            my $taken  = ($4 eq '-') ? 0 : $4;
            $data{$file}[BRANCH]{$branch} += $taken;
        }
    }
    close INFO;

    foreach $file (keys %data) {
        my $prev_cover = $cover_line;
        my $prev_total = $total_line;
        foreach (values %{ $data{$file}[LINE] }) {
            $cover_line++ if $_;
            $total_line++;
        }

        foreach (values %{ $data{$file}[FUNC] }) {
            $cover_func++ if $_;
            $total_func++;
        }

        foreach (values %{ $data{$file}[BRANCH] }) {
            $cover_branch++ if $_;
            $total_branch++;
        }

        my $suffix = lc(suffixname($file));
        $cover_file_by{$suffix}[0]++;
        $cover_file_by{$suffix}[1] += $cover_line - $prev_cover;
        $cover_file_by{$suffix}[2] += $total_line - $prev_total;
    }
}   #endof sub read_info

sub write_xml {
    my $xmlfile = shift;
    open XML, '>', $xmlfile or die "Create file error: $!\n";

    print XML <<EOF;
<?xml version="1.0"?>
<lcov>
  <coverage-line>$cover_line</coverage-line>
  <total-line>$total_line</total-line>
  <coverage-branch>$cover_branch</coverage-branch>
  <total-branch>$total_branch</total-branch>
  <coverage-function>$cover_func</coverage-function>
  <total-function>$total_func</total-function>
  <files>
EOF
    foreach my $suffix (keys %cover_file_by) {
        printf XML "    <file type='%s' count='%d' coverage-line='%d' total-line='%d'/>\n",
               $suffix, @{$cover_file_by{$suffix}};
    }
    print XML "  </files>\n</lcov>\n";
    close XML;
}   #endof sub write_xml
